import React, { useEffect, useState } from 'react';
import {
  Box,
  CartSummaryItem,
  Dialog,
  MainButton,
  MainColorType,
  makeToast,
  ModalHeader,
  SingleSelect,
  Text,
} from '@nova-hf/ui';
import { IContext } from 'beta/typings/context';
import { formatPrice } from 'beta/utils/helpers';
import { useTranslation } from 'beta/utils/i18n';
import { useRouter } from 'next/router';
import {
  ContractStatus,
  EquipmentRentalStatus,
  useContractsQuery,
  useFiberOrderStatusLazyQuery,
  useRemoveUndeliveredDeviceItemsMutation,
  useSendDeviceItemsToNavMutation,
  useServiceQuery,
} from 'typings/graphql';

import { SectionHeader } from '../comoponents/SectionHeader';

import {
  KASTARI_VARIANT_ID,
  ROUTER_25X_VAIANT_ID,
  ROUTER_VARIANT_ID,
} from './FiberServiceContainer';

const MAX_DEVICE_RENTAL_AMOUNT = 5;

type FiberDevicesProps = {
  color?: MainColorType;
};

const FiberDevices = ({ color }: FiberDevicesProps) => {
  const { t } = useTranslation(['fiber']);
  const router = useRouter();

  const serviceId = typeof router?.query?.serviceId === 'string' ? router?.query?.serviceId : '';
  const customerId = typeof router?.query?.customerId === 'string' ? router?.query?.customerId : '';

  const [numberOfKastarar, setNumberOfKastarar] = useState(0);
  const [numberOfRouters, setNumberOfRouters] = useState(0);
  const [numberOfRouters25x, setNumberOfRouters25x] = useState(0);
  const [price, setPrice] = useState('');
  const [storeId, setStoreId] = useState('');
  const [shouldHideDeviceCheckout, setShouldHideDeviceCheckout] = useState(false);
  const [showModal, setShowModal] = useState(false);

  const { loading: serviceLoading, error: serviceError } = useServiceQuery({
    variables: {
      serviceId: serviceId,
    },
    skip: !serviceId,
    onCompleted(data) {
      if (data?.service?.__typename === 'FiberService' && data?.service?.fiberOrderId) {
        fiberOrderStatus({
          variables: {
            input: {
              fiberOrderId: data.service.fiberOrderId,
            },
          },
        });
      }
    },
  });

  const {
    data: contractData,
    loading: contractLoading,
    error: contractError,
  } = useContractsQuery({
    variables: {
      input: {
        serviceId,
        customerId,
      },
    },
    onCompleted(data) {
      if (data.contracts.contracts.length) {
        const activeOrPendingContract = data?.contracts?.contracts?.find(
          (contract) =>
            contract.status === ContractStatus.Active || contract.status === ContractStatus.Pending,
        );
        const devices = activeOrPendingContract?.contractItems.filter(
          (item) => item.__typename === 'DeviceContractItem',
        );

        const kastarar = devices?.filter(
          (item) =>
            item.__typename === 'DeviceContractItem' &&
            item.status === EquipmentRentalStatus.Pending &&
            !item.rentalInfo?.externalOrderId &&
            item?.variant?.id === KASTARI_VARIANT_ID,
        );
        const routers = devices?.filter(
          (item) =>
            item.__typename === 'DeviceContractItem' &&
            item.status === EquipmentRentalStatus.Pending &&
            !item.rentalInfo?.externalOrderId &&
            item?.variant?.id.includes(ROUTER_VARIANT_ID),
        );

        const routers25x = devices?.filter(
          (item) =>
            item.__typename === 'DeviceContractItem' &&
            item.status === EquipmentRentalStatus.Pending &&
            !item.rentalInfo?.externalOrderId &&
            item?.variant?.id.includes(ROUTER_25X_VAIANT_ID),
        );

        if (!kastarar?.length && !routers?.length && !routers25x?.length)
          setShouldHideDeviceCheckout(true);
        if (kastarar?.length) setNumberOfKastarar(kastarar?.length);
        if (routers?.length) setNumberOfRouters(routers?.length);
        if (routers25x?.length) setNumberOfRouters25x(routers25x?.length);
      }
    },
    skip: !serviceId || !customerId,
  });

  const [
    fiberOrderStatus,
    { data: fiberOrderData, loading: fiberOrderLoading, error: fiberOrderError },
  ] = useFiberOrderStatusLazyQuery();

  const [removeDevices, { loading: removeDevicesLoading }] =
    useRemoveUndeliveredDeviceItemsMutation({
      onCompleted(data) {
        if (data?.removeUndeliveredDeviceItems?.id) {
          makeToast.success(
            t('fiberDevices.removeSuccess'),
            t('fiberDevices.removeSuccessSubtitle'),
          );
          setShowModal(false);
          handleHideFiberDeviceWindow();
        }
      },
      onError(error) {
        if (error) {
          makeToast.danger(t('fiberDevices.removeFailure'), error.message);
          setShowModal(false);
        }
      },
    });

  const [sendToNav, { loading: sendToNavLoading }] = useSendDeviceItemsToNavMutation({
    onCompleted(data) {
      if (data?.sendDeviceItemsToNav?.id) {
        makeToast.success(t('fiberDevices.sendSuccess'), '');
        handleHideFiberDeviceWindow();
      }
    },
    onError(error) {
      if (error) {
        makeToast.danger(t('fiberDevices.sendFailure'), error.message);
      }
    },
  });

  const isLoading = serviceLoading || contractLoading || fiberOrderLoading;
  const hasError = serviceError || contractError || fiberOrderError;

  const activeOrPendingContract = contractData?.contracts?.contracts?.find(
    (contract) =>
      contract.status === ContractStatus.Active || contract.status === ContractStatus.Pending,
  );

  const devices = activeOrPendingContract?.contractItems.filter(
    (item) => item.__typename === 'DeviceContractItem',
  );

  const handleRemoveDevices = () => {
    setShowModal(false);
    removeDevices({
      variables: {
        input: {
          id: activeOrPendingContract?.id ?? '',
        },
      },
    });
  };

  const handleSendToNav = () => {
    sendToNav({
      variables: {
        input: {
          contractId: activeOrPendingContract?.id ?? '',
          navisionStoreId: storeId,
          deliveredDevices: [
            {
              amount: numberOfKastarar,
              variantId: KASTARI_VARIANT_ID,
            },
            {
              amount: numberOfRouters,
              variantId: ROUTER_VARIANT_ID,
            },
            {
              amount: numberOfRouters25x,
              variantId: ROUTER_25X_VAIANT_ID,
            },
          ],
        },
      },
    });
  };

  const handleHideFiberDeviceWindow = () => {
    setShouldHideDeviceCheckout(true);
  };

  const increment = (variantId: string) => {
    if (variantId === ROUTER_VARIANT_ID && numberOfRouters < MAX_DEVICE_RENTAL_AMOUNT) {
      setNumberOfRouters(numberOfRouters + 1);
    } else if (
      variantId === ROUTER_25X_VAIANT_ID &&
      numberOfRouters25x < MAX_DEVICE_RENTAL_AMOUNT
    ) {
      setNumberOfRouters25x(numberOfRouters25x + 1);
    } else if (numberOfKastarar < MAX_DEVICE_RENTAL_AMOUNT) {
      setNumberOfKastarar(numberOfKastarar + 1);
    }
  };

  const decrement = (variantId: string) => {
    if (variantId === ROUTER_VARIANT_ID) {
      setNumberOfRouters(numberOfRouters - 1);
    } else if (variantId === ROUTER_25X_VAIANT_ID) {
      setNumberOfRouters25x(numberOfRouters25x - 1);
    } else {
      setNumberOfKastarar(numberOfKastarar - 1);
    }
  };

  const uniqueDevices = [
    ...new Set(
      devices
        ?.filter(
          (device) =>
            device.status === EquipmentRentalStatus.Pending &&
            device.__typename === 'DeviceContractItem' &&
            !device.rentalInfo?.externalOrderId,
        )
        ?.map((device) => device?.variant?.id),
    ),
  ];

  useEffect(() => {
    const router = devices?.find(
      (item) =>
        item.__typename === 'DeviceContractItem' &&
        item.status === EquipmentRentalStatus.Pending &&
        !item.rentalInfo?.trackingCode &&
        item?.variant?.id.includes(ROUTER_VARIANT_ID),
    );

    const router25x = devices?.find(
      (item) =>
        item.__typename === 'DeviceContractItem' &&
        item.status === EquipmentRentalStatus.Pending &&
        !item.rentalInfo?.trackingCode &&
        item?.variant?.id.includes(ROUTER_25X_VAIANT_ID),
    );

    const kastari = devices?.find(
      (item) =>
        item.__typename === 'DeviceContractItem' &&
        item.status === EquipmentRentalStatus.Pending &&
        !item.rentalInfo?.trackingCode &&
        item?.variant?.id.includes(KASTARI_VARIANT_ID),
    );
    const routerPrice = router?.variant?.monthlyCharge ?? 0;
    const router25xPrice = router25x?.variant?.monthlyCharge ?? 0;
    const kastariPrice = kastari?.variant?.monthlyCharge ?? 0;

    const raterTotal = routerPrice * numberOfRouters;
    const router25xTotal = numberOfRouters25x * router25xPrice;
    const kastariTotal = kastariPrice * numberOfKastarar;

    setPrice(formatPrice(kastariTotal + raterTotal + router25xTotal));
  }, [numberOfRouters, numberOfKastarar, numberOfRouters25x]);

  // If fiber order gets a visit from the provider, they will bring the devices
  const fiberOrderNeedsVisit = !!fiberOrderData?.fiberOrder?.needsVisit;

  // If hasPendingDevicesWithoutNavId is true, it means there are some pending devices without a tracking code (nav id) that need to be checked out with nav
  const hasPendingDevicesWithoutNavId = devices?.some(
    (item) =>
      item.__typename === 'DeviceContractItem' &&
      item?.rentalInfo?.status === EquipmentRentalStatus.Pending &&
      !item.rentalInfo.externalOrderId,
  );

  const findCorrespondingQuantity = (variantId: string) => {
    if (variantId === ROUTER_25X_VAIANT_ID) return numberOfRouters25x;
    if (variantId === ROUTER_VARIANT_ID) return numberOfRouters;
    if (variantId === KASTARI_VARIANT_ID) return numberOfKastarar;
  };

  const findCorrespondingPrice = (variantId: string, price: number) => {
    if (variantId === ROUTER_25X_VAIANT_ID) return numberOfRouters25x * price;
    if (variantId === ROUTER_VARIANT_ID) return numberOfRouters * price;
    if (variantId === KASTARI_VARIANT_ID) return numberOfKastarar * price;
  };

  if (
    isLoading ||
    hasError ||
    fiberOrderNeedsVisit ||
    (!devices?.length && !hasPendingDevicesWithoutNavId) ||
    shouldHideDeviceCheckout
  )
    return null;

  return (
    <>
      <Box boxShadow="normal" padding={5}>
        <SectionHeader headerTitle={t('fiberDevices.deviceService')} />
        <Box width="8/12">
          <Text marginTop={7} marginBottom={4} variant="pLargeRegular">
            {t('fiberDevices.where')}
          </Text>
        </Box>
        <SingleSelect
          color={color ?? 'purple'}
          defaultMenuIsOpen={false}
          placeholder={t('fiberDevices.shop')}
          id="verslanir"
          label={t('fiberDevices.store')}
          maxMenuHeight={250}
          onChange={(e) => setStoreId(e?.value ?? '')}
          isClearable={false}
          options={[
            {
              label: t('fiberDevices.lagmuli'),
              value: 'lagmuli',
            },
            {
              label: t('fiberDevices.smari'),
              value: 'smari',
            },
            {
              label: t('fiberDevices.kringlan'),
              value: 'kringlan2',
            },
            {
              label: t('fiberDevices.akureyri'),
              value: 'akureyri',
            },
            {
              label: t('fiberDevices.selfoss'),
              value: 'selfoss',
            },
          ]}
          required
        />
        <Box borderBottomStyle="solid" borderWidth="2px" borderColor="grey300" marginTop={5}>
          <Box marginBottom={2}>
            <Text variant="pSmallBold">{t('fiberDevices.devices')}</Text>
          </Box>
          {uniqueDevices.map((deviceId) => {
            const device = devices?.find(
              (d) => d?.variant?.id === deviceId && d.__typename === 'DeviceContractItem',
            );
            if (!device?.variantId) return null;
            return (
              <CartSummaryItem
                key={device?.id}
                title={device?.variant?.name ?? t('fiberDevices.unknown')}
                quantity={findCorrespondingQuantity(device.variantId)}
                price={findCorrespondingPrice(
                  device?.variantId,
                  device?.variant?.monthlyCharge ?? 0,
                )}
                onIncrement={() => increment(device?.variant?.id ?? '')}
                onDecrement={() => decrement(device?.variant?.id ?? '')}
                minDecrementValue={0}
                color={color ?? 'purple'}
              />
            );
          })}
        </Box>
        <Box
          marginTop={2}
          display="flex"
          flexDirection="row"
          justifyContent="space-between"
          alignItems="center"
        >
          <Text variant="pSmallBold">{t('fiberDevices.total')}</Text>
          <Text variant="pSmallBold">{price}</Text>
        </Box>
        <Box marginTop={5} display="flex" flexDirection="row" gap={5}>
          <MainButton
            colorScheme="white"
            dottedShadow="none"
            text={t('fiberDevices.cancel')}
            onClick={() => setShowModal(true)}
            isDisabled={removeDevicesLoading || sendToNavLoading}
          />
          <MainButton
            colorScheme={color ?? 'purple'}
            dottedShadow="none"
            text={t('fiberDevices.finish')}
            onClick={() => handleSendToNav()}
            icon="longArrowRight"
            isLoading={removeDevicesLoading || sendToNavLoading}
            isDisabled={!storeId || (numberOfKastarar === 0 && numberOfRouters === 0)}
          />
        </Box>
      </Box>
      <Dialog
        ariaLabel={t('fiberDevices.modalLabel')}
        onVisibilityChange={(isVisible: boolean) => setShowModal(isVisible)}
        isVisible={showModal}
        width={['11/12', '10/12', '6/12']}
      >
        <Box display="flex" flexDirection="column">
          <ModalHeader title={t('fiberDevices.modalTitle')} color={color} />
          <Box marginY={5} flexGrow={1}>
            {t('fiberDevices.modalDescription')}
          </Box>
          <Box display="flex" flexDirection={['column', 'row', 'row']} gap={4}>
            <MainButton
              text={t('fiberDevices.modalClose')}
              colorScheme="white"
              onClick={() => setShowModal(false)}
              dottedShadow="none"
            />
            <MainButton
              text={t('fiberDevices.modalConfirm')}
              colorScheme={color}
              icon="checkMark"
              onClick={() => handleRemoveDevices()}
              dottedShadow="none"
            />
          </Box>
        </Box>
      </Dialog>
    </>
  );
};

FiberDevices.getInitialProps = ({ pathname, query }: IContext) => {
  return {
    pathname,
    serviceId: query.serviceId,
    namespacesRequired: ['fiber'],
  };
};

export default FiberDevices;
